/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.avbravo.m21couchdb;

/**
 *
 * @author avbravo
 */
import com.fourspaces.couchdb.Database;
import com.fourspaces.couchdb.Document;
import com.fourspaces.couchdb.Session;
import com.fourspaces.couchdb.ViewResults;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;
import org.marc4j.MarcReader;
import org.marc4j.MarcStreamReader;
import org.marc4j.marc.DataField;
import org.marc4j.marc.Leader;
import org.marc4j.marc.Record;
import org.marc4j.marc.Subfield;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.StatusDisplayer;

/**
 *
 * @author avbravo
 */
public class Sesion {

    FileWriter fstream;
    BufferedWriter out;
    String directorio = "";
    private static String urlArchivo;
    private static String nombreArchivo;
    private static String proceso;
    Record record;
    MarcReader reader;
    Leader leader;
    private static String ipCouchdb = "localhost";
    private static int puertoCouchdb = 5984;
    private static String userCouchdb;
    private static String passwordCouchdb;
    private static String prefijo;
    private static String nuevo = "si";
    public static Session dbSession;
    public static Database db;
    public static Document doc;
    //  static DatabaseMetaData dmd;
    int num_columnas;
//    static List<String> ListaTablas = new ArrayList<String>();
    static List<String> ListaMensajes = new ArrayList<String>();
    int msgTypeError = NotifyDescriptor.ERROR_MESSAGE;
    int msgType = NotifyDescriptor.INFORMATION_MESSAGE;
    NotifyDescriptor d;
    //modelo para el jTable donde se mostrara el historial
    DefaultTableModel modelo;
    String codigo, texto;
    int largo;

    List<String> databasesCouchdb;

    public DefaultTableModel getModelo() {
        return modelo;
    }

    public void setModelo(DefaultTableModel modelo) {
        this.modelo = modelo;
    }

    public static String getProceso() {
        return proceso;
    }

    public static void setProceso(String proceso) {
        Sesion.proceso = proceso;
    }

    public static String getNombreArchivo() {
        return nombreArchivo;
    }

    public static void setNombreArchivo(String nombreArchivo) {
        Sesion.nombreArchivo = nombreArchivo;
    }

    public static String getNuevo() {
        return nuevo;
    }

    public static void setNuevo(String nuevo) {
        Sesion.nuevo = nuevo;
    }

    public static String getUrlArchivo() {
        return urlArchivo;
    }

    public static void setUrlArchivo(String urlArchivo) {
        Sesion.urlArchivo = urlArchivo;
    }

    public static List<String> getListaMensajes() {
        return ListaMensajes;
    }

    public static void setListaMensajes(List<String> ListaMensajes) {
        Sesion.ListaMensajes = ListaMensajes;
    }

    public static String getPrefijo() {
        return prefijo;
    }

    public static void setPrefijo(String prefijo) {
        Sesion.prefijo = prefijo;
    }

    public String getIpCouchdb() {
        return ipCouchdb;
    }

    public void setIpCouchdb(String ipCouchdb) {
        this.ipCouchdb = ipCouchdb;
    }

    public String getPasswordCouchdb() {
        return passwordCouchdb;
    }

    public void setPasswordCouchdb(String passwordCouchdb) {
        this.passwordCouchdb = passwordCouchdb;
    }

    public int getPuertoCouchdb() {
        return puertoCouchdb;
    }

    public void setPuertoCouchdb(int puertoCouchdb) {
        this.puertoCouchdb = puertoCouchdb;
    }

    public String getUserCouchdb() {
        return userCouchdb;
    }

    public void setUserCouchdb(String userCouchdb) {
        this.userCouchdb = userCouchdb;
    }
 
    /*
     *inicio
     */
    public boolean ConectarCouchDB() {
        try {
            dbSession = new Session(ipCouchdb, puertoCouchdb);
            String host = dbSession.getHost();
            //
            //  dbSession
          databasesCouchdb = dbSession.getDatabaseNames();

            StatusDisplayer.getDefault().setStatusText("host..." + dbSession.getHost());
            if (dbSession == null) {
                return false;
            }
            return true;
        } catch (Exception ex) {

            JOptionPane.showMessageDialog(null, "ConectarCouchDB()\nMensaje: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            this.ListaMensajes.add("ConectarCouchDB) " + ex.getLocalizedMessage().toString());
            StatusDisplayer.getDefault().setStatusText("ConectarCouchDB. Error " + ex.getMessage().toString());
        }
        return false;
    }



    public boolean CrearBaseDatos(String dbname) {
        try {
            db = dbSession.createDatabase(dbname);
            if (db == null) {
                return false;

            }
            return true;
        } catch (Exception ex) {
            //  JOptionPane.showMessageDialog(null, "CrearBaseDatos()\nMensaje: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            this.ListaMensajes.add("CrearBaseDatos(String dbname) " + ex.getLocalizedMessage().toString());
            StatusDisplayer.getDefault().setStatusText("CrearBaseDatos(String dbname). Error " + ex.getMessage().toString());
              d = new NotifyDescriptor.Message("CrearBaseDatos() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);
        }
        return false;
    }

    public boolean AbrirBaseDatos(String dbname) {
        try {
            db = dbSession.getDatabase(dbname);
            if (db == null) {
                return false;
            }
            return true;
        } catch (Exception ex) {

            //  JOptionPane.showMessageDialog(null, "AbrirBaseDatos()\nMensaje: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            this.ListaMensajes.add("AbrirBaseDatos(String dbname) " + ex.getLocalizedMessage().toString());
            StatusDisplayer.getDefault().setStatusText("AbrirBaseDatos(String dbname). Error " + ex.getMessage().toString());
            d = new NotifyDescriptor.Message("AbrirBaseDatos() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);
        }
        return false;
    }

    public void AgregarDocumentos() {
        try {

            doc = new Document();
            doc.setId("myid");
            doc.put("nombre", "valor");

            db.saveDocument(doc);
        } catch (Exception ex) {
            this.ListaMensajes.add("AgregarDocumentos " + ex.getLocalizedMessage().toString());
            StatusDisplayer.getDefault().setStatusText("AgregarDocumentos(). Error " + ex.getMessage().toString());
            d = new NotifyDescriptor.Message("AgregarDocumentos() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);

        }

    }

    public void MigrarArchivo() {
        try {
            CargarArchivo();
          //  GuardarHistorial();

        } catch (Exception ex) {

            StatusDisplayer.getDefault().setStatusText("procesarTabla(). Error " + ex.getMessage().toString());
            this.ListaMensajes.add("MigrarArchivo() " + ex.getLocalizedMessage().toString());
            d = new NotifyDescriptor.Message("MigrarArchivo() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);
        }
    }

    public boolean CargarArchivo() {
        try {
            fstream = new FileWriter("/home/avbravo/Documentos/marc-json.txt");
            out = new BufferedWriter(fstream);
            InputStream in = new FileInputStream(urlArchivo);
            if (in != null) {
                reader = new MarcStreamReader(in);
                while (reader.hasNext()) {
// obtener el registro completo mostrando todos los campos
                    record = reader.next();
                    // System.out.println(record.toString());
                    ObtenerRegistroMarc();

                }

            } else {
                d = new NotifyDescriptor.Message("No se encontro el archivo " + urlArchivo, msgTypeError);
                DialogDisplayer.getDefault().notify(d);
            }
            out.close();
            return true;
        } catch (Exception ex) {

            d = new NotifyDescriptor.Message("CargarArchivo() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);

        }
        return false;
    }

    public void ObtenerRegistroMarc() {
        try {
            doc = new Document();


            leader = record.getLeader();
            //no se usa el id para que couchdb lo genere mejor
            //  doc.setId(leader.toString());
            doc.put("leader", leader.toString());


            //Close the output stream

            List fields = record.getControlFields();
//          control field (tags 001  a 009 size " + fields.size() )
            StringBuffer strControlfield = new StringBuffer("[");
            for (int i = 0; i < fields.size(); i++) {
                //descompongo el elemento
                largo = fields.get(i).toString().length();

                codigo = fields.get(i).toString().substring(0, 3);
                texto = fields.get(i).toString().substring(4, largo);
                texto = texto.trim();
                if (codigo.equals("001")) {
                    out.newLine();
                    out.write("--------------------------------");
                  
                    out.newLine();
                   out.write(texto + "  leader " + leader.toString());
                  doc.setId(texto);
                }


                texto = EliminaCaracteres(texto, '"');
                if (i == 0) {
                    strControlfield.append("{\"tag\":");

                } else {
                    strControlfield.append(",{\"tag\":");

                }

                strControlfield.append("\"" + codigo + "\"");
                strControlfield.append(",\"data\":");
                strControlfield.append("\"" + texto + "\"}");



            }

            strControlfield.append("]");
            doc.put("controlfield", strControlfield.toString());
            ObtenerDataField();
            db.saveDocument(doc);

        } catch (Exception ex) {
            this.ListaMensajes.add("ObtenerRegistroMarc() " + ex.getLocalizedMessage().toString());
            d = new NotifyDescriptor.Message("ObtenerRegistroMarc() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);
        }
    }

    /*
     *
     * Obtiene los data field
     */
    private void ObtenerDataField() {
        try {

            // returns fields for tags 010 through 999
            StringBuffer strDatafield = new StringBuffer("[");
            List fields2 = record.getDataFields();

            String codigo_anterior = "";
            // int contador = 0;

            for (int i = 0; i < fields2.size(); i++) {

                largo = fields2.get(i).toString().length();
                codigo = fields2.get(i).toString().substring(0, 3);
                texto = fields2.get(i).toString().substring(4, largo);
                texto = texto.trim();
                //  doc.put(codigo, texto);
                //

                // get all occurences for a particular tag
                //      DataField field = (DataField) record.getVariableField(codigo);
                // get all occurences for a particular tag
                //test
                // si es el mismo codigo indica que ya proceso esa etiqueta
                if (codigo.equals(codigo_anterior)) {
                } else {



                    List subjects = record.getVariableFields(codigo);
                    for (int k = 0; k < subjects.size(); k++) {

                        DataField fieldee = (DataField) subjects.get(k);
                        String xtag = fieldee.getTag();
                        char xind1 = fieldee.getIndicator1();
                        char xind2 = fieldee.getIndicator2();

                        if (k == 0) {
                            strDatafield.append("{\"tag\":");

                        } else {

                            strDatafield.append(",{\"tag\":");

                        }
                        strDatafield.append("\"" + codigo + "\"");
                        strDatafield.append(",\"ind\":");
                        strDatafield.append("\"" + xind1 + xind2 + "\",");

                        strDatafield.append("\"subfield\":");
                        strDatafield.append("[");

                        List x = fieldee.getSubfields();
                        Iterator xx = x.iterator();

// aqui crear los subcampos para ese codigo

                        boolean control = true;
                        while (xx.hasNext()) {

                            Subfield mm = (Subfield) xx.next();
                            char code = mm.getCode();
                            String data = mm.getData();
                            data = data.trim();

                            data = EliminaCaracteres(data, '"');

                            if (control) {
                                strDatafield.append("{\"code\":");
                                control = false;

                            } else {
                                strDatafield.append(",{\"code\":");

                            }

                            strDatafield.append("\"" + code + "\"");
                            strDatafield.append(",\"data\":");
                            strDatafield.append("\"" + data + "\"}");

                        }

                        strDatafield.append("]");
                        strDatafield.append("}");

                    }
                    if (i < fields2.size() - 1) {

                        strDatafield.append(",");
                    }
                }
                codigo_anterior = codigo;

            }


            strDatafield.append("]");

            doc.put("datafield", strDatafield.toString());
        } catch (Exception ex) {
            this.ListaMensajes.add("ObtenerDataField() " + ex.getLocalizedMessage().toString());
            d = new NotifyDescriptor.Message("ObtenerDataField() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);
        }

    }

    private void GuardarHistorial() {
        try {


            if (AbrirBaseDatos("historial_migracion_marc") == false) {
                if (CrearBaseDatos("historial_migracion_marc") == false) {
                    d = new NotifyDescriptor.Message("No se puede crear la base de datos historial_migracion. \n No se registrara el historial.", msgType);
                    DialogDisplayer.getDefault().notify(d);
                    return;
                }
                if (AbrirBaseDatos("historial_migracion_marc") == false) {
                    d = new NotifyDescriptor.Message("No se puede abrir la base de datos historial_migracion.", msgType);
                    DialogDisplayer.getDefault().notify(d);
                    return;
                }
            }
            doc = new Document();
            doc.put("archivo", this.nombreArchivo);
            java.util.Calendar ca = java.util.Calendar.getInstance();
            java.sql.Date mydate = new java.sql.Date(ca.getTimeInMillis());

            Format formatter;
            formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
            //    Date fecha = rs.getDate("fechaarreglopago");
            String MyFecha = formatter.format(mydate);

            doc.put("fecha", MyFecha);
            doc.put("prefijo", this.prefijo);
            doc.put("proceso", this.proceso);



            db.saveDocument(doc);
        } catch (Exception ex) {
            d = new NotifyDescriptor.Message("GuardarHistorial() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);
        }
    }

    public boolean ObtenerHistorial(String dbname) {
        try {


            db = dbSession.getDatabase(dbname);
            if (db == null) {
                return false;
            }

            int count = db.getDocumentCount();
            if (count == 0) {
                d = new NotifyDescriptor.Message("No existen documentos de la base de datos " + dbname, msgType);
                DialogDisplayer.getDefault().notify(d);
                return false;
            }

            ViewResults results = db.getAllDocuments();



            //definimos el los campos para mostrar en el jtable
            Object[] filas = new Object[4]; // Hay tres columnas en la tabla


            for (Document document : results.getResults()) {
                //  System.out.println("id:" + document.getId());	 // Oops
                String id = (String) document.get("id");
                //  System.out.println("id:" + id); 		// Here "id" is correct

                Document full = db.getDocument(document.getId());
                String lnombre = full.getString("archivo");
                String lfecha = full.getString("fecha");
                String lprefijo = full.getString("prefijo");
                String lproceso = full.getString("proceso");
                //    System.out.println("Name:" + full.getString("archivo"));
                filas[0] = lnombre;
                filas[1] = lfecha;
                filas[2] = lprefijo;
                filas[3] = lproceso;

                modelo.addRow(filas);

            }

            return true;
        } catch (Exception ex) {

            d = new NotifyDescriptor.Message("ObtenerRegistros()  " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);
        }
        return false;
    }

    public String EliminaCaracteres(String s_cadena, char caracter) {
        String nueva_cadena = "";
        try {


            // Character caracter = null;

            /* Va recorriendo la cadena s_cadena y copia a la cadena que va a regresar,
            sólo los caracteres que no estén en la cadena s_caracteres */
            for (int i = 0; i < s_cadena.length(); i++) {


                if (s_cadena.charAt(i) == caracter) {

                    nueva_cadena += "'";
                } else {
                    nueva_cadena += s_cadena.charAt(i);
                }
            }

            return nueva_cadena;
        } catch (Exception ex) {
            d = new NotifyDescriptor.Message("EliminaCaracteres() " + ex.getLocalizedMessage().toString(), msgTypeError);
            DialogDisplayer.getDefault().notify(d);
            return s_cadena;
        }
    }
}
